//
//  SlicingVector.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/6/19.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef SlicingVector_hpp
#define SlicingVector_hpp

#include <stdio.h>
#include <functional>
/*
 1、vector中保存对象，派生类被裁剪问题
 std::vector<Base11> v;
 v.push_back(Base11("alex",5));
 v.push_back(Derived11("pushaka",3));
 
 for (int count = 0; count < v.size(); ++count)
 std::cout << "I am a " << v[count].getName() << " with value " << v[count].getValue() << "\n";
 
 //结果:仍然是对象裁剪了
 I am a Base with value 5
 I am a Base with value 3
 
 
 2、可以解决上面的问题
 std::vector<Base11 *> v;
 Base11 *b1 = new Base11();
 Derived11 *d1 = new Derived11();
 v.push_back(b1);
 v.push_back(d1);
 
 for (int count = 0; count < v.size(); ++count)
 std::cout << "I am a " << v[count]->getName() << " with value " << v[count]->getValue() << "\n";
 

 for (int count = 0; count < v.size(); ++count)
 delete v[count];
 
 //结果:
 I am a Base with value 0
 I am a Derived with value 0
 
 
 3、还有一种方法可以解决这个问题。 标准库提供了一个有用的解决方法：std :: reference_wrapper类。 实质上，std :: reference_wrapper是一个类似引用的类，但也允许赋值和复制，所以它与std :: vector兼容。
 1）std :: reference_wrapper存在于<functional>头文件中
 2）当你创建你的std :: reference_wrapper包装对象时，该对象不能是一个匿名对象（因为匿名对象具有表达式作用域会离开引用悬空）
 3）当你想让你的对象退出std :: reference_wrapper时，你使用get（）成员函数。

 
 std::vector<std::reference_wrapper<Base11>> v;
 Base11 b1("alex",3);
 Derived11 d1("jack",5);
 
 v.push_back(b1);
 v.push_back(d1);
 
 for (int count = 0; count < v.size(); ++count)
 std::cout << "I am a " << v[count].get().getName() << " with value " << v[count].get().getValue() << "\n";
 
 //结果:
 I am a Base with value 3
 I am a Derived with value 5
 
 
 //结论:
 尽管C ++支持通过对象切片将派生对象分配给基础对象，但通常情况下，这很可能不会导致头痛，您通常应该尽量避免切片。确保你的函数参数是引用（或指针），并且当涉及派生类时尽量避免任何类型的传值。
 
 */


#endif /* SlicingVector_hpp */
